﻿namespace C11_Ex02_1
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    public class CardGameLogics
    {
        const int BoardMinimumSize = 4;
        const int BoardMaximumSize = 6;
        private Player m_Player1;
        private Player m_Player2;
        private CardsTable m_Board;
        private PlayerTurn m_Turn;
        private bool m_IsFirstMove;
        private BoardPosition m_FirstChoise;
        private BoardPosition m_SecondChoise;
        private ComputerAI m_Computer;

        enum PlayerTurn
        {
            player1,
            player2
        }

        public string WinnerInMatch
        {
            get
            {
                return (m_Player1.GameScore > m_Player2.GameScore) ? m_Player1.Name : m_Player2.Name;
            }
        }

        public int WinnerPairs
        {
            get
            {
                return (m_Player1.GameScore > m_Player2.GameScore) ? m_Player1.GameScore : m_Player2.GameScore;
            }
        }

        public int Player1GamesWonAmount
        { 
            get { return m_Player1.AmountOfGamesWon; }
        }

        public int Player2GamesWonAmount
        {
            get { return m_Player2.AmountOfGamesWon; }
        }
        
        public String Player1Name
        {
            get { return m_Player1.Name; }
            set { m_Player1.Name = value; }
        }

        public String Player2Name
        {
            get { return m_Player2.Name; }
            set { m_Player2.Name = value; }
        }

        public Opponent.eTypeOfOpponent Player2type
        {
            set { m_Player2.PlayerType = value; }
            get { return m_Player2.PlayerType; }
        }

        public CardsTable Board
        {
            get { return m_Board; }
        }

        public CardGameLogics()
        {
            m_Player1 = new Player();
            m_Player2 = new Player();
            m_Turn = PlayerTurn.player1;
            m_IsFirstMove = true;
        }

        public bool IsDimensionValid(int i_Dimension)
        {
            return (i_Dimension >= BoardMinimumSize && i_Dimension <= BoardMaximumSize);
        }

        public bool DoesBoardContainsEvenSquaresAmount(int i_BoardColumns, int i_BoardRows)
        {
            bool ReturnValue = false;

            if ((i_BoardColumns % 2 == 0) || (i_BoardRows % 2 == 0))
            {
                ReturnValue = true;
            }

            return ReturnValue;
        }

        public void CreateBoard(int i_BoardRows, int i_BoardColumns)
        {
            if (!(m_Board == null))
            {
                // using the garbage collector's abilities
                m_Board = null;
            }

            m_Board = new CardsTable(i_BoardColumns, i_BoardRows);
        }

        public bool WasMacthEnded()
        {
            return !m_Board.AreThereAnyHiddenCards();
        }

        public bool IsWithinLegalBounds(BoardPosition o_UserSelectedPosition)
        {
            return m_Board.IsCoordinateInBoardRange(o_UserSelectedPosition);
        }

        public bool IsCellRevealed(BoardPosition o_UserSelectedPosition)
        {
            return m_Board.IsCellRevealed(o_UserSelectedPosition);
        }

        public void DoAndSaveMoves(BoardPosition i_Position)
        {
            if (m_IsFirstMove)
            {
                m_Board.OpenCell(i_Position);
                m_FirstChoise = i_Position;
                m_IsFirstMove = false;
            }
            else
            {
                m_Board.OpenCell(i_Position);
                m_SecondChoise = i_Position;
                m_IsFirstMove = true;
            }
        }

        public void TestRoundResult()
        {
            if (!m_Board.CompareCellsValues(m_FirstChoise, m_SecondChoise))
            {
                m_Board.CloseCell(m_FirstChoise);
                m_Board.CloseCell(m_SecondChoise);
                switchPlayersTurns();
            }
            else
            {
                increasePlayerGameScore();
            }
        }

        private void switchPlayersTurns()
        {
            if (m_Turn == PlayerTurn.player1)
            {
                m_Turn = PlayerTurn.player2;
            }
            else
            {
                m_Turn = PlayerTurn.player1;
            }
        }

        private void increasePlayerGameScore()
        {
            if (m_Turn == PlayerTurn.player1)
            {
                m_Player1.IncreaseGameScore();
            }
            else
            {
                m_Player2.IncreaseGameScore();
            }
        }
        
        public bool CreateComputer()
        {
            ComputerAI.ComputerType ChoseComputerType = ComputerAI.ComputerType.Easy;
            bool IsAComputer = true;

            switch (m_Player2.PlayerType)
            {
                case Opponent.eTypeOfOpponent.ComputerEasy:
                    ChoseComputerType = ComputerAI.ComputerType.Easy;
                    break;
                case Opponent.eTypeOfOpponent.ComputerNormal:
                    ChoseComputerType = ComputerAI.ComputerType.Normal;
                    break;
                case Opponent.eTypeOfOpponent.ComputerHard:
                    ChoseComputerType = ComputerAI.ComputerType.Hard;
                    break;
                case Opponent.eTypeOfOpponent.Human:
                    IsAComputer = false;
                    break;
                default:
                    IsAComputer = false;
                    break;
            }

            if (IsAComputer)
            {
                m_Computer = new ComputerAI(ChoseComputerType);
            }
            return IsAComputer;
        }

        public BoardPosition ComputerMove()
        {
            return m_Computer.CalculateComputerNextMove(m_Board);
        }

        public bool Player1Turn()
        {
            return m_Turn == PlayerTurn.player1;
        }

        public void IncreaseWinnerGamesWonAmount()
        {
            if (m_Player1.GameScore > m_Player2.GameScore)
            {
                m_Player1.IncreaseGamesWon();
            }
            else
            {
                m_Player2.IncreaseGamesWon();
            }
        }
    }
}
